<

ScaffoldMessenger によって管理される SnackBars

まとめ

SnackBar内のAPIScaffold現在は、ScaffoldMessenger、そのうちの1つは のコンテキスト内でデフォルトで利用可能MaterialApp

コンテクスト

この変更の前は、SnackBarを呼び出すと表示されます でScaffold現在の範囲内でBuildContext。 電話することでScaffold.of(context).showSnackBar、 現在Scaffoldをアニメーション化しますSnackBar視界に入る。 これは現在にのみ適用されますScaffold、 変更された場合、ルート間で保持されません。 その過程でSnackBarさんのプレゼンテーション。 次の場合にもエラーが発生します。showSnackBarの実行中に呼び出されます 非同期イベント、およびBuildContext無効になった ルート変更と、Scaffold処分されてる。

ScaffoldMessenger今はハンドルしますSnackBarするために ルート間で持続し、常に現在のルートに表示されます。Scaffold。 デフォルトでは、ルートScaffoldMessengerに含まれていますMaterialApp、 ただし、独自の制御スコープを作成することもできます。ScaffoldMessengerさらにコントロールするためにどれの Scaffoldあなたのものを受け取りますSnackBars.

変更内容の説明

以前のアプローチでは、Scaffoldを示すSnackBar

Scaffold(
  key: scaffoldKey,
  body: Builder(
    builder: (BuildContext context) {
      return GestureDetector(
        onTap: () {
          Scaffold.of(context).showSnackBar(SnackBar(
            content: const Text('snack'),
            duration: const Duration(seconds: 1),
            action: SnackBarAction(
              label: 'ACTION',
              onPressed: () { },
            ),
          ));
        },
        child: const Text('SHOW SNACK'),
      );
    },
  )
);

新しいアプローチでは、ScaffoldMessenger見せる のSnackBar。この場合、Builderもうありません 新しいスコープを提供するために必要ですBuildContextそれか の「下」にありますScaffold

Scaffold(
  key: scaffoldKey,
  body: GestureDetector(
    onTap: () {
      ScaffoldMessenger.of(context).showSnackBar(SnackBar(
        content: const Text('snack'),
        duration: const Duration(seconds: 1),
        action: SnackBarAction(
          label: 'ACTION',
          onPressed: () { },
        ),
      ));
    },
    child: const Text('SHOW SNACK'),
  ),
);

を提示するとき、SnackBar移行中に、 のSnackBarを完了しますHeroアニメーション、 スムーズに次のページに進みます。

ScaffoldMessengerすべての子孫が含まれるスコープを作成します。Scaffold受け取るために登録してくださいSnackBarさん、 これが、これらの遷移をまたいで持続する方法です。 ルートを使用する場合ScaffoldMessengerによって提供されるMaterialApp、すべての子孫Scaffold受け取りますSnackBarさん、 新品でない限りScaffoldMessengerスコープはツリーのさらに下に作成されます。 独自のインスタンスを作成することで、ScaffoldMessenger、 どちらを制御できるかScaffold受け取りますSnackBarに基づいていないもの アプリケーションのコンテキストに基づいて。

方法debugCheckHasScaffoldMessengerアサートすることが可能です 与えられたコンテキストにはScaffoldMessenger祖先。 を提示しようとしていますSnackBarなしでScaffoldMessenger祖先 present の結果は次のようなアサーションになります。

No ScaffoldMessenger widget found.
Scaffold widgets require a ScaffoldMessenger widget ancestor.
Typically, the ScaffoldMessenger widget is introduced by the MaterialApp
at the top of your application widget tree.

移行ガイド

移行前のコード:

// The ScaffoldState of the current context was used for managing SnackBars.
Scaffold.of(context).showSnackBar(mySnackBar);
Scaffold.of(context).hideCurrentSnackBar(mySnackBar);
Scaffold.of(context).removeCurrentSnackBar(mySnackBar);

// If a Scaffold.key is specified, the ScaffoldState can be directly
// accessed without first obtaining it from a BuildContext via
// Scaffold.of. From the key, use the GlobalKey.currentState
// getter. This was previously used to manage SnackBars.
final GlobalKey<ScaffoldState> scaffoldKey = GlobalKey<ScaffoldState>();
Scaffold(
  key: scaffoldKey,
  body: ...,
);

scaffoldKey.currentState.showSnackBar(mySnackBar);
scaffoldKey.currentState.hideCurrentSnackBar(mySnackBar);
scaffoldKey.currentState.removeCurrentSnackBar(mySnackBar);

移行後のコード:

// The ScaffoldMessengerState of the current context is used for managing SnackBars.
ScaffoldMessenger.of(context).showSnackBar(mySnackBar);
ScaffoldMessenger.of(context).hideCurrentSnackBar(mySnackBar);
ScaffoldMessenger.of(context).removeCurrentSnackBar(mySnackBar);

// If a ScaffoldMessenger.key is specified, the ScaffoldMessengerState can be directly
// accessed without first obtaining it from a BuildContext via
// ScaffoldMessenger.of. From the key, use the GlobalKey.currentState
// getter. This is used to manage SnackBars.
final GlobalKey<ScaffoldMessengerState> scaffoldMessengerKey = GlobalKey<ScaffoldMessengerState>();
ScaffoldMessenger(
  key: scaffoldMessengerKey,
  child: ...
)

scaffoldMessengerKey.currentState.showSnackBar(mySnackBar);
scaffoldMessengerKey.currentState.hideCurrentSnackBar(mySnackBar);
scaffoldMessengerKey.currentState.removeCurrentSnackBar(mySnackBar);

// The root ScaffoldMessenger can also be accessed by providing a key to 
// MaterialApp.scaffoldMessengerKey. This way, the ScaffoldMessengerState can be directly accessed
// without first obtaining it from a BuildContext via ScaffoldMessenger.of. From the key, use
// the GlobalKey.currentState getter.
final GlobalKey<ScaffoldMessengerState> rootScaffoldMessengerKey = GlobalKey<ScaffoldMessengerState>();
MaterialApp(
  scaffoldMessengerKey: rootScaffoldMessengerKey,
  home: ...
)

rootScaffoldMessengerKey.currentState.showSnackBar(mySnackBar);
rootScaffoldMessengerKey.currentState.hideCurrentSnackBar(mySnackBar);
rootScaffoldMessengerKey.currentState.removeCurrentSnackBar(mySnackBar);

タイムライン

リリースされたバージョン: 1.23.0-13.0.pre
安定版リリース: 2.0.0

参考文献

API ドキュメント:

  • Scaffold
  • ScaffoldMessenger
  • SnackBar
  • MaterialApp

関連する問題:

  • 問題 #57218
  • 問題 #62921

関連する PR:

  • 足場メッセンジャー
  • ScaffoldMessenger の移行